
package com.dog.basics.service.wishwash.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.dog.basics.bean.dto.admin.wishwash.*;
import com.dog.basics.bean.dto.api.wishwash.ApiBindingCodeDto;
import com.dog.basics.bean.dto.api.wishwash.ApiUserLoginDto;
import com.dog.basics.bean.model.sys.SysUser;
import com.dog.basics.bean.model.sys.SysUserInfo;
import com.dog.basics.bean.model.wishwash.DogHxDevNode;
import com.dog.basics.bean.model.wishwash.DogHxField;
import com.dog.basics.bean.model.wishwash.DogHxOrderItme;
import com.dog.basics.bean.vo.admin.sys.AdminUserInfoVo;
import com.dog.basics.bean.vo.admin.wishwash.AdminDogHxDevRateVo;
import com.dog.basics.bean.vo.api.wishwash.ApiDogHxDevInfoVo;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.util.PageParam;
import com.dog.basics.common.util.SpringContextUtils;
import com.dog.basics.common.util.ToolUtil;
import com.dog.basics.dao.sys.SysUserInfoMapper;
import com.dog.basics.dao.sys.SysUserMapper;
import com.dog.basics.dao.wishwash.DogHxDevNodeMapper;
import com.dog.basics.dao.wishwash.DogHxFieldMapper;
import com.dog.basics.dao.wishwash.DogHxOrderItmeMapper;
import com.dog.basics.mqtt.send.IMqttSender;
import com.dog.basics.security.util.SecurityUtils;
import com.dog.basics.bean.vo.admin.wishwash.AdminDogHxDevVo;
import com.dog.basics.bean.vo.admin.wishwash.AdminDogHxDevInfoVo;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

import com.dog.basics.service.sys.SysUserRoleService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dog.basics.bean.model.wishwash.DogHxDev;
import com.dog.basics.dao.wishwash.DogHxDevMapper;
import com.dog.basics.service.wishwash.DogHxDevService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 设备信息
 *
 * @author cy code generator
 * @date 2021-07-09 17:40:27
 */
@Service
@AllArgsConstructor
public class DogHxDevServiceImpl extends ServiceImpl<DogHxDevMapper, DogHxDev> implements DogHxDevService {

    private final DogHxOrderItmeMapper hxOrderItmeMapper;
    private final SysUserInfoMapper userInfoMapper;
    private final SysUserMapper userMapper;
    private final DogHxFieldMapper fieldMapper;
    private final DogHxDevNodeMapper devNodeMapper;
    private final PasswordEncoder passwordEncoder;

    /**
     * @Description: 后台管理分页
     * @Param: status
     * @return: IPage
     * @author cy code generator
     * @date 2021-07-09 17:40:27
     */
    @Override
    public IPage<AdminDogHxDevVo> getAdminPageList(PageParam page, AdminDogHxDevFromDto obj) {
        if (!SecurityUtils.hasRole(CommonConstants.ROLE_ADMIN_CODE)) {
            // 判断代理商
            if (SecurityUtils.hasRole(CommonConstants.ROLE_AGENT_CODE)) {
                obj.setFieldAgentId(SecurityUtils.getSysUser().getUserId());
            }
            // 判断场地负责人
            if (SecurityUtils.hasRole(CommonConstants.ROLE_FIELD_CODE)) {
                List<Long> longs = fieldMapper.selectList(Wrappers.<DogHxField>lambdaQuery().select(DogHxField::getId).eq(DogHxField::getFieldUserId, SecurityUtils.getSysUser().getUserId())).stream().map(e -> e.getId()).collect(Collectors.toList());
                obj.setFields(CollUtil.isNotEmpty(longs) ? longs : CollUtil.newArrayList(CommonConstants.MENU_TREE_ROOT_ID));
            }
        }
        // 后台管理 - 分页查询数据信息
        this.page(page, Wrappers.<DogHxDev>lambdaQuery()
                .eq(ObjectUtil.isNotNull(obj.getFieldAgentId()), DogHxDev::getFieldId,obj.getFieldAgentId())
                .in(CollUtil.isNotEmpty(obj.getFields()), DogHxDev::getFieldId,obj.getFields())
                .eq(ObjectUtil.isNotNull(obj.getDevSizeType()), DogHxDev::getDevSizeType, obj.getDevSizeType())
                .eq(StrUtil.isNotBlank(obj.getDevName()), DogHxDev::getDevName, obj.getDevName())
                .eq(StrUtil.isNotBlank(obj.getDevCode()), DogHxDev::getDevCode, obj.getDevCode())
                .eq(ObjectUtil.isNotNull(obj.getDevState()), DogHxDev::getDevState, obj.getDevState())
                .between(ObjectUtil.isNotNull(obj.getStartTime()) && ObjectUtil.isNotNull(obj.getEndTime()), DogHxDev::getCreateTime, obj.getStartTime(), obj.getEndTime())
                .orderBy(Boolean.TRUE, obj.getIsOrderByAvg(), DogHxDev::getCreateTime));
        // 格式化数据信息
        List<DogHxDev> records = page.getRecords();
        page.setRecords(records.stream().map(e -> {
            // 数据信息转换
            AdminDogHxDevVo objVo = BeanUtil.toBean(e, AdminDogHxDevVo.class);
            // 查询代理商信息
            if (ObjectUtil.isNotNull(objVo.getFieldId()) && !Validator.equal(objVo.getFieldId(), CommonConstants.DEFAULT_VAL_LONG)) {
                DogHxField hxField = fieldMapper.selectById(objVo.getFieldId());
                objVo.setFieldName(ObjectUtil.isNotNull(hxField) ? hxField.getFieldName() : "");
                if (ObjectUtil.isNotNull(hxField)) {
                    SysUserInfo userInfo = userInfoMapper.selectById(hxField.getFieldAgentId());
                    objVo.setAgentName(ObjectUtil.isNotNull(userInfo) ? userInfo.getRealName() : "");
                }
            }
            // 查询使用次数
            Integer count1 = hxOrderItmeMapper.selectCount(Wrappers.<DogHxOrderItme>lambdaQuery().eq(DogHxOrderItme::getDevId, e.getId()));
            objVo.setUseCount(count1);
            // 查询总收入
            BigDecimal sum = hxOrderItmeMapper.getIncomeSumByDevId(e.getId(), null, null);
            objVo.setIncomeSum(sum);
            // 查询一拖机
            Integer count2 = devNodeMapper.selectCount(Wrappers.<DogHxDevNode>lambdaQuery().eq(DogHxDevNode::getDevId, e.getId()));
            objVo.setDevDragFew(count2);
            return objVo;
        }).collect(Collectors.toList()));
        // 数据返回
        return page;
    }

    /**
     * @Description: 后台管理查询详情
     * @Param: obj
     * @return: Boolean
     * @author cy code generator
     * @date 2021-07-09 17:40:27
     */
    @Override
    public AdminDogHxDevInfoVo getAdminObjXq(Long id) {
        // 后台管理 - 查询数据信息是否存在
        DogHxDev obj = this.getById(id);
        // 判断数据是否存在
        Validator.validateNotNull(obj, "ommon.noData");
        // 数据信息格式化 - 返回
        AdminDogHxDevInfoVo objVo = BeanUtil.toBean(obj, AdminDogHxDevInfoVo.class);
        // 查询设备场地
        DogHxField hxField = fieldMapper.selectById(obj.getFieldId());
        if (ObjectUtil.isNotNull(hxField)) {
            objVo.setFieldName(hxField.getFieldName());
            objVo.setFieldAddrs(hxField.getFieldDetailedAddress());
        }
        // 查询设备代理商信息
        if (ObjectUtil.isNotNull(obj.getFieldId()) && !Validator.equal(obj.getFieldId(), CommonConstants.DEFAULT_VAL_LONG)) {
            SysUserInfo userInfo = userInfoMapper.selectById(obj.getAgentId());
            SysUser user = userMapper.selectById(obj.getAgentId());
            objVo.setAgentName(ObjectUtil.isNotNull(userInfo) ? userInfo.getRealName() : "");
            objVo.setAgentPhone(ObjectUtil.isNotNull(user) ? user.getPhone() : "");
        }
        // 设备子节点数
        Integer count = devNodeMapper.selectCount(Wrappers.<DogHxDevNode>lambdaQuery().eq(DogHxDevNode::getDevId, id));
        objVo.setDevNodeCount(count);
        // 查询设备本月流水
        BigDecimal incomeSumByDevId = hxOrderItmeMapper.getIncomeSumByDevId(obj.getId(), ToolUtil.dateSecond(DateUtil.beginOfMonth(DateUtil.date())), ToolUtil.dateSecond(DateUtil.endOfMonth(DateUtil.date())));
        objVo.setThisMonthLius(incomeSumByDevId);
        // 查询设备昨日使用率
        Integer rateByDevId = hxOrderItmeMapper.getUtilizationRateByDevId(obj.getId(), ToolUtil.dateSecond(DateUtil.beginOfDay(DateUtil.yesterday())), ToolUtil.dateSecond(DateUtil.endOfDay(DateUtil.yesterday())));
        rateByDevId = ObjectUtil.isNotNull(rateByDevId) ? rateByDevId : 0;
        BigDecimal mul = NumberUtil.mul(NumberUtil.div(rateByDevId, objVo.getDevNodeCount()), BigDecimal.valueOf(100));
        objVo.setYesterdayUtilizationRate(mul);
        // 查询设备七天使用率
        List<AdminDogHxDevRateVo> rateVos = CollUtil.newArrayList();
        for (int i = 7; i > 0; i--) {
            DateTime yesterday = DateUtil.offsetDay(DateUtil.date(), BigDecimal.valueOf(i).negate().intValue());
            Integer rate = hxOrderItmeMapper.getUtilizationRateByDevId(obj.getId(), ToolUtil.dateSecond(DateUtil.beginOfDay(yesterday)), ToolUtil.dateSecond(DateUtil.endOfDay(yesterday)));
            rate = ObjectUtil.isNotNull(rate) ? rate : 0;
            BigDecimal mul1 = NumberUtil.mul(NumberUtil.div(rate, objVo.getDevNodeCount()), BigDecimal.valueOf(100));
            AdminDogHxDevRateVo vo = new AdminDogHxDevRateVo();
            vo.setTime(DateUtil.formatDate(yesterday));
            vo.setVal(mul1);
            rateVos.add(vo);
        }
        objVo.setSevenDayUtilizationRate(rateVos);
        return objVo;
    }


    /**
     * @Description: 后台管理增加
     * @Param: obj
     * @return: Boolean
     * @author cy code generator
     * @date 2021-07-09 17:40:27
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveAdminObj(AdminDogHxDevAddDto obj) {
        // 判断设备编码是否存在
        int count = this.count(Wrappers.<DogHxDev>lambdaQuery().eq(DogHxDev::getDevCode, obj.getDevCode()));
        Validator.validateFalse(SqlHelper.retBool(count), "dev.code.exists");
        // 后台管理 - 数据信息转换
        DogHxDev objAdd = BeanUtil.toBean(obj, DogHxDev.class);
        // 数据信息补充
        objAdd.setCreateTime(DateUtil.currentSeconds());
        objAdd.setCreateBy(SecurityUtils.getSysUser().getUserId());
        // 执行添加数据信息
        Validator.validateTrue(this.save(objAdd), "common.save");
        return Boolean.TRUE;
    }


    /**
     * @Description: 后台管理修改
     * @Param: obj
     * @return: Boolean
     * @author cy code generator
     * @date 2021-07-09 17:40:27
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editAdminObj(AdminDogHxDevEditDto obj) {
        // 查询数据信息是否存在
        DogHxDev objInfo = this.getById(obj.getId());
        // 判断数据是否存
        Validator.validateNotNull(objInfo, "ommon.noData");
        // 判断是否修改了编码
        if (!Validator.equal(objInfo.getDevCode(), obj.getDevCode())) {
            // 判断设备编码是否存在
            int count = this.count(Wrappers.<DogHxDev>lambdaQuery().eq(DogHxDev::getDevCode, obj.getDevCode()));
            Validator.validateFalse(SqlHelper.retBool(count), "The same device code already exists");
        }
        // 数据信息转换
        DogHxDev editObj = BeanUtil.toBean(obj, DogHxDev.class);
        // 补充数据信息
        editObj.setUpdateTime(DateUtil.currentSeconds());
        editObj.setUpdateBy(SecurityUtils.getSysUser().getUserId());
        // 执行修改信息
        Validator.validateTrue(this.updateById(editObj), "common.edit");
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 授权金额
     * @author He
     * @date 2021/9/23
     */
    @Override
    public Boolean updateMoneById(AdminDogHxDevModeDto obj) {
        // 查询数据信息是否存在
        DogHxDev objInfo = this.getById(obj.getId());
        // 判断数据是否存
        Validator.validateNotNull(objInfo, "ommon.noData");
        // 远程授权金额
        SpringContextUtils.getBean(IMqttSender.class).sendToMqtt(StrUtil.format("/DEV/{}/MONEY", objInfo.getDevCode()), JSONUtil.toJsonStr(obj));
        return Boolean.TRUE;
    }


    /**
     * @Description: 删除
     * @Param: ids
     * @return: Boolean
     * @author cy code generator
     * @date 2021-07-09 17:40:27
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteObj(Long id) {
        // 查询数据信息 - 根据标识
        DogHxDev objInfo = this.getById(id);
        // 判断数据信息是否
        Validator.validateNotNull(objInfo, "common.noData");
        // 执行删除数据信息
        Validator.validateTrue(this.removeById(id), "common.del");
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 绑定代理商
     * @author He
     * @date 2021/7/15
     */
    @Override
    public Boolean editBdAgentIds(AdminDogHxDevBdAgentDto dto) {
        // 查询代理商是否存在、判断代理商是否代理商
        Boolean isUserCode = SpringContextUtils.getBean(SysUserRoleService.class).getIsUserCode(dto.getAgentId(), CommonConstants.ROLE_AGENT_CODE);
        Validator.validateTrue(isUserCode, "dev.choice.noAgent");
        // 查询设备信息是否存在
        Validator.validateTrue(CollUtil.isNotEmpty(dto.getDevIds()), "dev.code.noNull");
        // 设备组装数据修改
        List<DogHxDev> hxDevs = CollUtil.newArrayList();
        for (int i = 0; i < dto.getDevIds().size(); i++) {
            DogHxDev hxDev = new DogHxDev();
            hxDev.setId(dto.getDevIds().get(i));
            hxDev.setAgentId(dto.getAgentId());
            hxDev.setUpdateTime(DateUtil.currentSeconds());
            hxDev.setUpdateBy(SecurityUtils.getSysUser().getUserId());
            hxDevs.add(hxDev);
        }
        // 判断修改数据信息
        if (CollUtil.isNotEmpty(hxDevs)) {
            boolean b = this.updateBatchById(hxDevs);
            Validator.validateTrue(b, "common.edit");
        }
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 绑定场地
     * @author He
     * @date 2021/7/15
     */
    @Override
    public Boolean editBdfieldIds(AdminDogHxDevBdfieldDto dto) {
        // 查询场地是否存
        DogHxField hxField = fieldMapper.selectById(dto.getFieldId());
        Validator.validateNotNull(hxField, "ommon.noData");
        // 设备组装数据修改
        List<DogHxDev> hxDevs = CollUtil.newArrayList();
        for (int i = 0; i < dto.getDevIds().size(); i++) {
            DogHxDev hxDev = new DogHxDev();
            hxDev.setId(dto.getDevIds().get(i));
            hxDev.setFieldId(dto.getFieldId());
            hxDev.setUpdateTime(DateUtil.currentSeconds());
            hxDev.setUpdateBy(SecurityUtils.getSysUser().getUserId());
            hxDevs.add(hxDev);
        }
        // 判断修改数据信息
        if (CollUtil.isNotEmpty(hxDevs)) {
            boolean b = this.updateBatchById(hxDevs);
            Validator.validateTrue(b, "common.edit");
        }
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 禁用启用设备
     * @author He
     * @date 2021/7/15
     */
    @Override
    public Boolean editAdminForbidden(Long devId) {
        // 查询设备是否存在
        DogHxDev hxDev = this.getById(devId);
        Validator.validateNotNull(hxDev, "ommon.noData");
        // 判断设备状态符合更改
        boolean contains = CollUtil.newArrayList(1, 2).contains(hxDev.getDevState());
        Validator.validateTrue(contains, "Inconsistent equipment status");
        // 判断状态
        DogHxDev editHxDev = new DogHxDev();
        editHxDev.setId(hxDev.getId());
        editHxDev.setDevState(Validator.equal(hxDev.getDevState(), 1) ? 2 : 1);
        editHxDev.setUpdateBy(SecurityUtils.getSysUser().getUserId());
        editHxDev.setUpdateTime(DateUtil.currentSeconds());
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 设备登录
     * @author He
     * @date 2021/8/3
     */
    @Override
    public ApiDogHxDevInfoVo getById(ApiBindingCodeDto dto) {
        // 根据设备编码查询设备是否存在
        List<DogHxDev> hxDevs = this.list(Wrappers.<DogHxDev>lambdaQuery().eq(DogHxDev::getDevCode, dto.getCode()));
        // 判断设备是否存在
        Validator.validateTrue(CollUtil.isNotEmpty(hxDevs), "Device does not exist");
        // 判断设备是否初始化 。 判断设备是否有绑定
        Validator.validateEqual(hxDevs.get(0).getDevState(), 1, "The equipment is abnormal");
        // 判断绑定是否一致
        Validator.validateEqual(hxDevs.get(0).getDevMac(), dto.getDevMac(), "Inconsistent MAC address binding");
        // 返回数据信息
        return BeanUtil.toBean(hxDevs.get(0), ApiDogHxDevInfoVo.class);
    }

    /**
     * @功能描述: 设备绑定
     * @author He
     * @date 2021/8/3
     */
    @Override
    public Boolean editBindingCodeDevice(ApiBindingCodeDto dto) {
        // 根据设备编码查询设备是否存在
        List<DogHxDev> hxDevs = this.list(Wrappers.<DogHxDev>lambdaQuery().eq(DogHxDev::getDevCode, dto.getCode()));
        // 判断设备是否存在
        Validator.validateTrue(CollUtil.isNotEmpty(hxDevs), "Device does not exist");
        // 判断设备是否初始化 。 判断设备是否有绑定
        if (!Validator.equal(hxDevs.get(0).getDevState(), 0)) {
            if (Validator.equal(hxDevs.get(0).getDevMac(), dto.getDevMac())) {
                return Boolean.TRUE;
            } else {
                Validator.validateTrue(Boolean.FALSE, "The equipment is abnormal");
            }
        }
        // 绑定设备
        DogHxDev hxDev = new DogHxDev();
        hxDev.setId(hxDevs.get(0).getId());
        hxDev.setDevState(1);
        hxDev.setDevMac(dto.getDevMac());
        hxDev.setUpdateTime(DateUtil.currentSeconds());
        Validator.validateTrue(this.updateById(hxDev), "common.save");
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 管理员登录
     * @author He
     * @date 2021/8/6
     */
    @Override
    public Boolean getLogin(ApiUserLoginDto dto) {
        // 查询设备是否存在
        DogHxDev hxDev = this.getById(dto.getDevId());
        Validator.validateNotNull(hxDev, "Device does not exist");
        // 查询用户是否存在
        AdminUserInfoVo byUsername = userMapper.getUserVoByUsername(dto.getUsername());
        Validator.validateNotNull(byUsername, "User information does not exist");
        // 判断密码是否正确
        Validator.validateTrue(passwordEncoder.matches(dto.getPassowrd(), byUsername.getPassword()), "Password error");
        // 查询设备是否绑定场地
        //DogHxField hxField = fieldMapper.selectById(hxDev.getFieldId());
        //Validator.validateNotNull(hxField, "Unbound site or site does not exist");
        // 判断是否所属本场地
        //Validator.validateEqual(hxField.getFieldUserId(), byUsername.getUserId(), "You are not a site account and cannot be managed");
        return Boolean.TRUE;
    }

}
